package compiladores;
import java.io.*;

public class Tradutor {

    //Maximo de instrucoes
    private final int I_LENGTH = 100;

    //Instrucoes MEPA
	private String[] codigoMEPA_ = new String[I_LENGTH*10];

    //Instrucoes em quadrupls
    private Quadrupla[] quads_ = new Quadrupla[I_LENGTH];

    //Tabela de simbolos
    private Tabela tabela = new Tabela();

    //tabela de desvios
    int mapa_[] = new int[I_LENGTH];

    //desvios
    int desvios_[] = new int[I_LENGTH];

	public Tradutor(){
	}

    //Le as quadruplas do arquivo
    public void leQuadruplas(String path) throws IOException {
        BufferedReader in = new BufferedReader(new FileReader(path));
        String str;
        int i =0;
        while ((str = in.readLine()) != null)
            quads_[i++] = new Quadrupla(str);
    }

    //Le a tabela de simbolos no arquivo
    public void leTabela(String path) throws Exception {
        BufferedReader in = new BufferedReader(new FileReader(path));
        String str;
        String tokens[] = new String[4];
        int i =0;
        while ((str = in.readLine()) != null) {
            tokens = str.split(" ");
            tabela.add(new Simbolo(tokens[0],tokens[1],Integer.parseInt(tokens[2]),Integer.parseInt(tokens[3])));
        }
    }

    //Le cada quadrupla e traduz
    public void traduz(){
        
        String operador="";
        String classe1="";
        String classe2="";
        String classe3="";
        int nivel1=0;
        int nivel2=0;
        int nivel3=0;
        int offset1=0;
        int offset2=0;
        int offset3=0;
        int contador = 0;

        for(int i=0;i<quads_.length;i++){
            if (quads_[i] == null)
                break;

            operador = quads_[i].getOperador();
            if(tabela.lookup(quads_[i].getOperando1()) != null){
                classe1 = tabela.lookup(quads_[i].getOperando1()).getClasse();
                nivel1 = tabela.lookup(quads_[i].getOperando1()).getNivel();
                offset1 = tabela.lookup(quads_[i].getOperando1()).getOffset(); 
            }
            if(tabela.lookup(quads_[i].getOperando2()) != null){
                classe2 = tabela.lookup(quads_[i].getOperando2()).getClasse();
                nivel2 = tabela.lookup(quads_[i].getOperando2()).getNivel();
                offset2 = tabela.lookup(quads_[i].getOperando2()).getOffset();
            }
            if(tabela.lookup(quads_[i].getOperando3()) != null){
                classe3 = tabela.lookup(quads_[i].getOperando3()).getClasse();
                nivel3 = tabela.lookup(quads_[i].getOperando3()).getNivel();
                offset3 = tabela.lookup(quads_[i].getOperando3()).getOffset();
            }
            //inicio
            if( operador.equals("inicio") )
                codigoMEPA_[contador++] = "INPP";

            //fim
            if( operador.equals("para") )
                codigoMEPA_[contador++] = "PARA";
    
            //amem
            else if( operador.equals("amem") )
                codigoMEPA_[contador++] = "AMEM "+quads_[i].getOperando1();
            
            
            //read
            else if( operador.equals("read") ){
                codigoMEPA_[contador++] = "LEIT";
                codigoMEPA_[contador++] = "ARMZ "+nivel3+" "+offset3;
            }

            //write
            else if( operador.equals("write") ){
                if( classe1.equals("const") )
                    codigoMEPA_[contador++] = "CRCT "+quads_[i].getOperando1();
                else
                    codigoMEPA_[contador++] = "CRVL "+nivel1+" "+offset1;
                codigoMEPA_[contador++] = "IMPR";
            }

			//entr
			else if( operador.equals("entr")){
				codigoMEPA_[contador++] = "ENTR "+quads_[i].getOperando1();
			}

			//rtpr
			else if( operador.equals("rtpr")){
				codigoMEPA_[contador++] = "RTPR "+quads_[i].getOperando1();
			}	

			//dmem
			else if( operador.equals("dmem")){
				codigoMEPA_[contador++] = "DMEM "+quads_[i].getOperando1();
			}

			//not
			else if( operador.equals("not") ){
                //constante
                if( classe1.equals("const") )
                    codigoMEPA_[contador++] = "CRCT "+quads_[i].getOperando1();
                else
                    codigoMEPA_[contador++] = "CRVL "+nivel1+" "+offset1;

                codigoMEPA_[contador++] = "NEGA";
                codigoMEPA_[contador++] = "ARMZ "+nivel3+" "+offset3;

            }
			//param
			else if( operador.equals("param") ){
				codigoMEPA_[contador++] = "CRVL "+nivel1+" "+offset1;
			}


			
            //operacoes
            //tem q colocar o resto das operacoes... preguica de digitar tudo
            else if( operador.equals("+") || operador.equals("-") || operador.equals("*") || operador.equals("/") ){
                
                //carrega operador 1
                //constante
                if( classe1.equals("const") )
                    codigoMEPA_[contador++] = "CRCT "+quads_[i].getOperando1();
                //variavel
                else
                    codigoMEPA_[contador++] = "CRVL "+nivel1+" "+offset1;
                
                //carrega operador 2
                //constante
                if( classe2.equals("const") )
                    codigoMEPA_[contador++] = "CRCT "+quads_[i].getOperando2();
                //variavel
                else
                    codigoMEPA_[contador++] = "CRVL "+nivel2+" "+offset2;

                //faz operacao
                if ( operador.equals("+") )
                    codigoMEPA_[contador++] = "SOMA";

                if ( operador.equals("-") )
                    codigoMEPA_[contador++] = "SUBT";

                if ( operador.equals("*") )
                    codigoMEPA_[contador++] = "MULT";

                if ( operador.equals("/") )
                    codigoMEPA_[contador++] = "DIVI";
                
                if ( operador.equals("<") )
                    codigoMEPA_[contador++] = "CMME";

                if ( operador.equals(">") ){
                    System.out.println("sadfsdf");
                    codigoMEPA_[contador++] = "CMMA";
                }

                if ( operador.equals("==") )
                    codigoMEPA_[contador++] = "CMIG";

                if ( operador.equals("!=") )
                    codigoMEPA_[contador++] = "CMDG";

                if ( operador.equals(">=") )
                    codigoMEPA_[contador++] = "CMAG";

                if ( operador.equals("<=") )
                    codigoMEPA_[contador++] = "CMDG";


                //armazena resultado
                codigoMEPA_[contador++] = "ARMZ "+nivel3+" "+offset3;

            }    
            
            //atribuicao
            else if( operador.equals(":=") ){
                //constante
                if( classe1.equals("const") )
                    codigoMEPA_[contador++] = "CRCT "+quads_[i].getOperando1();
                else
                    codigoMEPA_[contador++] = "CRVL "+nivel1+" "+offset1;

                codigoMEPA_[contador++] = "ARMZ "+nivel3+" "+offset3;
            }

            else if( operador.equals("-un") ){
                //constante
                if( classe1.equals("const") )
                    codigoMEPA_[contador++] = "CRCT "+quads_[i].getOperando1();
                else
                    codigoMEPA_[contador++] = "CRVL "+nivel1+" "+offset1;

                codigoMEPA_[contador++] = "INVR";
                codigoMEPA_[contador++] = "ARMZ "+nivel3+" "+offset3;
            }

           //if 
            else if( operador.equals("if") ){
                
                if( classe1.equals("const") )
                    codigoMEPA_[contador++] = "CRCT "+quads_[i].getOperando1();
                else
                    codigoMEPA_[contador++] = "CRVL "+nivel1+" "+offset1;

                codigoMEPA_[contador++] = "DSVF ";
                desvios_[contador-1] = Integer.parseInt(quads_[i].getOperando3());;
            }
			//goto
            else if( operador.equals("goto") ){
                codigoMEPA_[contador++] = "DSVS ";
                desvios_[contador-1] = Integer.parseInt(quads_[i].getOperando3());
            }

            //call
            else if( operador.equals("call") ){
                codigoMEPA_[contador++] = "CHPR ";
                desvios_[contador-1] = Integer.parseInt(quads_[i].getOperando3());
            }
            mapa_[i] = contador;

            //System.out.println(i+" "+quads_[i].getOperador()+" "+contador+" "+codigoMEPA_[contador-1]);
        } 

        //atualiza as instrucoes de desvio
        for(int i=0;i<desvios_.length;i++)
            if(desvios_[i] != 0){
                if(codigoMEPA_[i].equals("CHPR ")){
                    codigoMEPA_[i] += mapa_[desvios_[i]-1];
                    codigoMEPA_[i] += " 0";
                }
                else
                    codigoMEPA_[i] += mapa_[desvios_[i]-1];
            }
    }
    
    public void imprimeCodigo(){
        for(int i=0;i<codigoMEPA_.length;i++){
            if(codigoMEPA_[i] == null)
                break;
            System.out.println(codigoMEPA_[i]);
        }
    }
}
